Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: delay addition of issuer to auctioneer until a good time #8398

Merged
merged 5 commits into from
Oct 6, 2023

Conversation

Chris-Hibbert
Copy link
Contributor

@Chris-Hibbert Chris-Hibbert commented Sep 27, 2023

closes: #8347

Description

When adding a new asset type, delay until the auction is quiescent, so as not to trigger #8296.

Security Considerations

Don't break the chain.

Scaling Considerations

Not an issue here.

Documentation Considerations

Not applicable.

Testing Considerations

I added bootstrapTests that wait until a propitious or hazardous time to add the collateral, and verify that addAssetsToVault waits for the auction to quiesce, and succeeds in adding a new collateral type.

Upgrade Considerations

This applies to adding asset types, not upgrading contracts.

@Chris-Hibbert Chris-Hibbert self-assigned this Sep 27, 2023
@Chris-Hibbert
Copy link
Contributor Author

Chris-Hibbert commented Sep 28, 2023

@turadg

I added a test file. I haven't yet found the auction in order to query for the current auction schedule. I want to test running addAssetsToVaults at these times:

  • after an auction has started
  • more than 20 minutes before the next auction starts
  • less than 20 minutes before the next auction starts

I think those would cover all the interesting cases, though it may be that i'm not thinking of enough edge conditions, so just before an auction starts, or just before it completes might give results I don't expect.

@Chris-Hibbert Chris-Hibbert force-pushed the 8347-timing branch 3 times, most recently from 178cc76 to 6e90832 Compare October 4, 2023 22:36
@Chris-Hibbert Chris-Hibbert requested a review from turadg October 4, 2023 22:56
Copy link
Member

@turadg turadg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first pass

const addBrandThenResolve = ToFarFunction('addBrandThenResolve', async () => {
await E(auctioneerCreator).addBrand(interchainIssuer, keyword);
finishPromiseKit.resolve(true);
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this value read. I think this function is meant to be void.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

const finishPromiseKit = makePromiseKit();
const addBrandThenResolve = ToFarFunction('addBrandThenResolve', async () => {
await E(auctioneerCreator).addBrand(interchainIssuer, keyword);
finishPromiseKit.resolve(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this value read. I think it's meant to be:

Suggested change
finishPromiseKit.resolve(true);
finishPromiseKit.resolve(undefined);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

makeLiquidationTestContext,
} from './liquidation.ts';

const test = anyTest as TestFn<LiquidationTestContext>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grand

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this from a nearby test. I don't even know what it means. Care to explain? What's it do, and why is it "grand"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grand that you're using TS syntax ;-)

It means: "define test to be the value of anyTest with the type TestFn with its Context type parameter set to LiquidationTestContext". TestFn ensures that any test methods and descendants (like t) are typed The default t.context is unknown so the parameter slot fills that in with the actual context being assigned in line 16.

Though I see on line 30 that you're adding proposal to the context. To not get a type error, include it here.

Suggested change
const test = anyTest as TestFn<LiquidationTestContext>;
const test = anyTest as TestFn<LiquidationTestContext & { proposal: Awaited<ReturnType<typeof buildProposal>> }>;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though seeing further down, I don't think the raw proposal should go into the context because it's really more of a template. See request below for providing a helper function instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, though the declarations are a little more involved than that.

await advanceTimeTo(afterEndTime);

const schedulesAfter = await EV(auctioneerKit.creatorFacet).getSchedule();
// brand equality is broken
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how and why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TimeMath.compareAbs() complains that the brands don't match. I dunno why, but I suspect it's a result of whatever forces us to use EV here instead of E. How should I phrase that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised object identity of brands isn't preserved here. I thought maybe you were getting the brands from 2 different places - one from the kernel and one from vstorage - but not so; both are coming from calls to the creatorFacet by way of the kernel.

EV used to preserve object identity in such circumstances, I believe.

@gibson042 @FUDCo was there a regression in #8373 ? Or is my mental model just off?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's partially that your mental model is a bit off but there was a change that is part of the story here. You cannot directly compare object identity on the stuff you get back from EV, though reason is not actually EV itself but kmarshal, which previously had internal state that we've now gotten rid of because it was fundamentally incompatible with importation into different compartments. To address this there are now a handful of matchXXX functions in the same supports module with EV. To compare two object references (such as to brands) for equality, the one you want is matchRef.

(Though to be clear, there are some important limitations of EV that people seem to be oblivious to that they need to be more broadly educated about, but I don't think they're involved in this particular case.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot directly compare object identity on the stuff you get back from EV

noted. thanks for confirming.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the comment to clarify the reason it can't use TimeMath.compareAbs().

@dckc
Copy link
Member

dckc commented Oct 5, 2023

Does this somehow subsume the oracle constraint from #8347 ?

... it's crucial that the oracle be started before the auction ...

@Chris-Hibbert
Copy link
Contributor Author

Does this somehow subsume the oracle constraint from #8347 ?

... it's crucial that the oracle be started before the auction ...

It does not. If we're worried about that, we should add a check somewhere that an oracle is available.

@dckc
Copy link
Member

dckc commented Oct 5, 2023

Does this somehow subsume the oracle constraint from #8347 ?

... it's crucial that the oracle be started before the auction ...

It does not. If we're worried about that, we should add a check somewhere that an oracle is available.

My understanding of #8347 is that we are worried about that. Please do add a check that the oracle is available; for example, ask for (and await) a quote.

p.s. later discussion concluded that yes, this PR does subsume the oracle constraint check.

Copy link
Member

@turadg turadg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic of proposal and test look correct to me.

Please do the requested refactorings before merge.

makeLiquidationTestContext,
} from './liquidation.ts';

const test = anyTest as TestFn<LiquidationTestContext>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grand that you're using TS syntax ;-)

It means: "define test to be the value of anyTest with the type TestFn with its Context type parameter set to LiquidationTestContext". TestFn ensures that any test methods and descendants (like t) are typed The default t.context is unknown so the parameter slot fills that in with the actual context being assigned in line 16.

Though I see on line 30 that you're adding proposal to the context. To not get a type error, include it here.

Suggested change
const test = anyTest as TestFn<LiquidationTestContext>;
const test = anyTest as TestFn<LiquidationTestContext & { proposal: Awaited<ReturnType<typeof buildProposal>> }>;

});

test.after.always(t => {
// This will fail if a subset of tests are run. It detects that three
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this check? Is each test not independent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each test now ends by verifying that readLatest(${auctioneerPath}.book1) finds something. What's actually happening is that the tests will sequentially add book1, book2, and book3. In order to allow for parallelism, since they take so long, I didn't make them sequential, so I don't know what order they run in.

I could have each test check all three potentially-present nodes and verify that one has a matching name. I thought it more straightforward to verify in the .after that 3 had been added. Please let me know if you think there's a more legible approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now that I moved building the proposal into .before, the total time was 38s. When I modified the tests to .serial that grew to 40s, which is probably not significant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not significant. also probably a smaller difference in CI with fewer cores.

packages/boot/test/bootstrapTests/test-addAssets.ts Outdated Show resolved Hide resolved
makeLiquidationTestContext,
} from './liquidation.ts';

const test = anyTest as TestFn<LiquidationTestContext>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though seeing further down, I don't think the raw proposal should go into the context because it's really more of a template. See request below for providing a helper function instead.

packages/boot/test/bootstrapTests/test-addAssets.ts Outdated Show resolved Hide resolved
@Chris-Hibbert Chris-Hibbert added auction automerge:rebase Automatically rebase updates, then merge labels Oct 5, 2023
@mergify mergify bot merged commit 61383f9 into master Oct 6, 2023
71 checks passed
@mergify mergify bot deleted the 8347-timing branch October 6, 2023 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auction automerge:rebase Automatically rebase updates, then merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

timing work-around for stATOM proposal
4 participants